package com.fadis.data.zset;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.TreeMap;

/**
 * https://blog.csdn.net/w372426096/article/details/77800642
 * <p>
 * https://blog.csdn.net/universsky2015/article/details/102728114
 * <p>
 * https://github.com/williamfiset/Algorithms/blob/master/src/main/java/com/williamfiset/algorithms/datastructures/skiplist/SkipList.java
 * <p>
 * 跳表的java实现
 * java内置的ConcurrentSkipListMap好像满足不了rank的需求
 */
public class ZSkipList<T extends Comparable<T>> {

    private static boolean doubleEquals(double d1, double d2){
        return Math.abs(d1-d2) < 1e-17;
    }

    private static <T extends Comparable<T>> int strCompare(T d1, T d2){
        if(d1 == null && d2 == null) return 0;
        if(d1 == null) return -1;
        if(d2 == null) return 1;
        return d1.compareTo(d2);
    }

    public static final Random random = new Random(System.currentTimeMillis());
    public static final int ZSKIPLIST_MAXLEVEL = 32;

    private ZSkipListNode<T> header, tail;
    private long length = 0;
    private int level = 1;

    public ZSkipList() {
        create();
    }

    // 创建一个跳跃表
    private void create() {
        tail = null;
        length = 0;
        level = 0;
        header = createNode(ZSKIPLIST_MAXLEVEL, 0, null);
        for (int i = 0; i < header.level.length; i++) {
            header.level[i].span = 0;
            header.level[i].forward = null;
        }
    }

    // 创建一个层数为level的跳跃表节点
    public ZSkipListNode createNode(int level, double score, T obj) {
        ZSkipListNode<T> headerNode = new ZSkipListNode<T>();
        headerNode.obj = obj;
        headerNode.score = score;
        headerNode.level = new ZSkipListLevel[level];
        for (int i = 0; i < headerNode.level.length; i++) {
            headerNode.level[i] = new ZSkipListLevel();
            headerNode.level[i].span = 0;
            headerNode.level[i].forward = null;
        }
        headerNode.backward = null;
        return headerNode;
    }

    // 往跳跃表中插入一个新节点
    public void insert(double score, T obj) {

        int levelNew = getRandomLevel();
        int maxLevel = Math.max(levelNew, this.level);
        ZSkipListNode node = createNode(levelNew, score, obj);

        // 找到每一层需要插入的位置 -- 每一层将要插入其后的节点
        ZSkipListNode[] nodesWillAppend = getPrevNodeOnEveryLevel(score, obj, maxLevel, new WalkerScoreAndObj(CompareOp.greater_equals));
//        System.out.println("----插入" + obj + " == " + level + " == ");
//        for (int i = 0; i < nodesWillAppend.length; i++) {
//            System.out.print(nodesWillAppend[i].obj + ", ");
//        }
//        System.out.println();
        // 插入
//        for (int i = maxLevel - 1; i >= 0; i--) {
        for (int i = 0; i <= maxLevel - 1; i++) {
            int currentLevel = i;
            ZSkipListNode prev = nodesWillAppend[currentLevel];
            ZSkipListLevel prevLevelInfo = prev.level[currentLevel];

            ZSkipListNode next = prevLevelInfo.forward;


            if (currentLevel <= levelNew - 1) {
                // 需要插入节点
                prev.level[currentLevel] = new ZSkipListLevel(node);
                if (currentLevel == 0) node.backward = prev;

                node.level[currentLevel].forward = next;
                if(currentLevel == 0) {
                    if(next != null) next.backward = node;
                    else tail = node;
                }

                // 修改span
                prev.level[currentLevel].span = getDistanceInUnStableList(prev, node);
                if (next != null) {
                    node.level[currentLevel].span = getDistanceInUnStableList(node, next);
                }

            } else {
                // 只需要修改span
                if (next != null) {
                    prevLevelInfo.span += 1;
                }
            }
        }
//        dict.put(obj, score);

        // 更新信息
        length += 1;
        this.level = maxLevel;
//        System.out.println("插入完毕--" + obj);
    }


    // 找到每一层上的前序节点
    private ZSkipListNode[] getPrevNodeOnEveryLevel(double score, T obj, int maxLevel, NodeWalker walker) {
        ZSkipListNode[] nodesWillAppend = new ZSkipListNode[maxLevel];

        // 空表，返回header
        if(header.level[0].forward == null){
            for (int i = 0; i < maxLevel; i++) {
                nodesWillAppend[i] = header;
            }
            return nodesWillAppend;
        }

        ZSkipListNode searchStarter = header;

        for (int i = maxLevel - 1; i >= 0; i--) {
            int currentLevel = i;
            ZSkipListNode currentNode = searchStarter;

            while (true) {
//                System.out.println("继续找...");
                ZSkipListNode nextNode = currentNode.level[currentLevel].forward;
                if (nextNode == null || walker.shouldStop(nextNode, score, obj)) {
                    // 链表断了，或下一个节点满足要求，就继续去下一个层找
                    nodesWillAppend[currentLevel] = currentNode;
                    searchStarter = currentNode;
                    break;
                } else {
                    // 继续向后搜索
                    currentNode = nextNode;
                }
            }
        }

        return nodesWillAppend;
    }

//    // 找到每一层上的前序节点
//    private ZSkipListNode[] getPrevNodeOnEveryLevel2(double score, String obj, int maxLevel) {
//        ZSkipListNode[] nodesWillAppend = new ZSkipListNode[maxLevel];
//
//        // 空表，返回header
//        if(header.level[0].forward == null){
//            for (int i = 0; i < maxLevel; i++) {
//                nodesWillAppend[i] = header;
//            }
//            return nodesWillAppend;
//        }
//
//        ZSkipListNode searchStarter = header;
//
//        for (int i = maxLevel - 1; i >= 0; i--) {
//            int currentLevel = i;
//            ZSkipListNode currentNode = searchStarter;
//
//            while (true) {
////                System.out.println("继续找...");
//                ZSkipListNode nextNode = currentNode.level[currentLevel].forward;
//                if (nextNode == null) {
//                    // 链表断了，就往这里接上
//                    nodesWillAppend[currentLevel] = currentNode;
//                    searchStarter = currentNode;
//                    break;
//                } else if (doubleEquals(nextNode.score, score)) {
//                    // score相同，比较自然排序
//                    if (nextNode.obj.compareTo(obj) > 0) {
//                        nodesWillAppend[currentLevel] = currentNode;
//                        searchStarter = currentNode;
//                        break;
//                    } else {
//                        // 继续向后搜索
//                        currentNode = nextNode;
//                    }
//                } else if (nextNode.score > score) {
//                    // 此节点score大于新节点，就插入这个前面
//                    nodesWillAppend[currentLevel] = currentNode;
//                    searchStarter = currentNode;
//                    break;
//                } else {
//                    // 继续向后搜索
//                    currentNode = nextNode;
//                }
//            }
//        }
//        return nodesWillAppend;
//    }

    private int getDistanceInUnStableList(ZSkipListNode node1, ZSkipListNode node2) {
        int totalSpan = 0;

        ZSkipListNode currentNode = node1;
        while (true) {
            ZSkipListNode nextNode = currentNode.level[0].forward;
            if (doubleEquals(nextNode.score, node2.score) && nextNode.obj.compareTo(node2.obj) == 0) {
                break;
            } else  {
                totalSpan += 1;
            }
            currentNode = nextNode;
        }

//        System.out.println(node1.obj + " = " + node2.obj + "的距离：" + totalSpan);
        return totalSpan + 1;
    }

    // 删除节点函数，供zslDelete、zslDeleteByScore和zslDeleteByRank函数调用
    // void zslDeleteNode(zskiplist *zsl, zskiplistNode *x, zskiplistNode **update);
    public void delete(ZSkipListNode<T> node) {
        delete(node.score, node.obj);
    }

    // 从从跳跃表中删除一个分值score、保存对象为obj的节点
    public int delete(double score, T obj) {
        ZSkipListNode node = findFirstNode(score, obj, new WalkerScoreAndObj(CompareOp.equals), true);
        if (node == null) return 0;
        return 1;
    }

    public ZSkipListNode findFirstNode(double score, T obj, NodeWalker walker, boolean delete) {
        ZSkipListNode[] prevNodes = getPrevNodeOnEveryLevel(score, obj, this.level, walker);

        ZSkipListNode firstNodeMaybe = prevNodes[0].level[0].forward;
//        System.out.println("-----");
//        for (int i = prevNodes.length - 1; i >= 0; i--) {
//            System.out.println(prevNodes[i]);
//        }
//        System.out.println("-----");
//        ZSkipListNode firstNodeMaybe = walker.firstAcceptedNode(prevNodes[0], score, obj);

        if(firstNodeMaybe == null) return null;
        if(firstNodeMaybe == header) return firstNodeMaybe;
        if(!walker.absoluteAccept(firstNodeMaybe, score, obj)) return null;  // 要求equals时，如果firstNodeMaybe大于score+obj，那就是没找到


        if (delete) {
            for (int i = 0; i < this.level; i++) {
//                System.out.println("maybe ==> " + firstNodeMaybe);
                ZSkipListNode prev = prevNodes[i];

//                System.out.println("prev ==>" + prev);
                if (i < firstNodeMaybe.level.length) {
                    // 当前节点占用的层
                    ZSkipListNode next = firstNodeMaybe.level[i].forward;
                    System.out.println(prev);
                    prev.level[i].forward = next;
                    if (next != null) {
                        // 修改span
                        prev.level[i].span = getDistanceInUnStableList(prev, next);

                    }
                    if (i == 0) {
                        if(next == null) this.tail = prev;
                        else next.backward = prev;
                    }

                } else {
                    // 非当前节点占用的层，只需要修改span
                    if (prev.level[i].forward != null) {
                        prev.level[i].span -= 1;
                    }
                }
            }
            this.length -= 1;

            // 删除之后，层数可能会减少，这里简单处理，挨层检查一下
            int oldLevel = this.level;
            for (int i = oldLevel - 1; i >= 0; i--) {
                if (header.level[i].forward == null) {
                    // 这一层没了
                    this.level -= 1;

                    if (this.level == 1) break;
                } else {
                    break;
                }


            }
        }
        return firstNodeMaybe;
    }


    //  在跳跃表中删除所有分值在给定范围range内的节点
    public long deleteRangeByScore(double min, boolean minInclude, double max, boolean maxInclude, TreeMap<T, Double> dict) {
        double minScore = header.level[0].forward == null ? 0 : header.level[0].forward.score;
        double maxScore = tail == null ? 0 : tail.score;
        if(min > maxScore) return 0;
        if(max < minScore) return 0;
        if(min > max) return 0;

        ZSkipListNode nodeStart = findFirstNode(min, null, new WalkerScore(minInclude ? CompareOp.greater_equals : CompareOp.equals), false);
        if (nodeStart == null) return 0;
        long count = 0L;
        while (true) {
            if (nodeStart == null || (maxInclude ? nodeStart.score > max : nodeStart.score >= max)) {
                break;
            } else {
                delete(nodeStart);
                if(dict != null) dict.remove(nodeStart.obj);
                count++;
                nodeStart = nodeStart.level[0].forward;
            }
        }
        return count;
    }

    //  在跳跃表中删除给定排序范围的节点
    public long deleteRangeByRank(long min, long max, TreeMap<T, Double> dict) {
        if(min >= this.length) return 0;
        if (max < 0) return 0;
        if (min > max) return 0;

        if (min < 0) min = 0;
        if (max >= this.length) max = this.length-1;

        ZSkipListNode nodeStart = getElementByRank(min);
        ZSkipListNode nodeEnd = getElementByRank(max);

        int deleteCount = 0;
        while (true){
            ZSkipListNode next = nodeStart.level[0].forward;
            delete(nodeStart);
            if(dict != null) dict.remove(nodeStart.obj);
            deleteCount++;
            if(nodeStart.score == nodeEnd.score && nodeStart.obj.compareTo(nodeEnd.obj) == 0) break;
            nodeStart = next;
        }
        return deleteCount;
    }

    //  删除成员对象值在指定字典序范围的节点
    public long deleteRangeByLex(T min, boolean minInclude, T max, boolean maxInclude, TreeMap<T, Double> dict) {
        if(this.length == 0) return 0;

        ZSkipListNode start = null;
        if("-".equals(min)) {
            start = header.level[0].forward;
        }else{
            start = findFirstNode(0, min, new WalkerLex(minInclude ? CompareOp.greater_equals : CompareOp.greater), false);
        }
        if("+".equals(max)) {
            max = tail.obj;
            maxInclude = true;
        }

        if(start == null) return 0;

        List<ZSkipListNode> list = new ArrayList<>();
        while (start != null) {
            if((minInclude && start.obj.compareTo(min) >= 0)
                    || (!minInclude && start.obj.compareTo(min) > 0)){

                if((maxInclude && start.obj.compareTo(max) <= 0)
                        || (!maxInclude && start.obj.compareTo(max) < 0)){
                    ZSkipListNode rm = start;
                    start = start.level[0].forward;
                    delete(rm);
                    list.add(rm);
                    if(dict != null) dict.remove(rm.obj);
                }else{
                    break;
                }
            }else{
                break;
            }
        }

        return list.size();
    }

    public long lexCount(T min, boolean minInclude, T max, boolean maxInclude){
        if(this.length == 0) return 0;

        ZSkipListNode start = null;
        if("-".equals(min)) {
            start = header.level[0].forward;
        }else{
            start = findFirstNode(0, min, new WalkerLex(minInclude ? CompareOp.greater_equals : CompareOp.greater), false);
        }
        if("+".equals(max)) {
            max = tail.obj;
            maxInclude = true;
        }

        if(start == null) return 0;

        List<ZSkipListNode> list = new ArrayList<>();
        while (start != null) {
            if((minInclude && start.obj.compareTo(min) >= 0)
                    || (!minInclude && start.obj.compareTo(min) > 0)){

                if((maxInclude && start.obj.compareTo(max) <= 0)
                        || (!maxInclude && start.obj.compareTo(max) < 0)){
                    list.add(start);
                    start = start.level[0].forward;
                }else{
                    break;
                }
            }else{
                break;
            }
        }

        return list.size();
    }

    /*
    当有序集合的所有成员都具有相同的分值时， 有序集合的元素会根据成员的字典序（lexicographical ordering）来进行排序， 而这个命令则可以返回给定的有序集合键 key 中， 值介于 min 和 max 之间的成员。

如果有序集合里面的成员带有不同的分值， 那么命令返回的结果是未指定的（unspecified）。

特殊值 + 和 - 在 min 参数以及 max 参数中具有特殊的意义， 其中 + 表示正无限， 而 - 表示负无限

【ZRANGEBYLEX <zset> - +】--> 返回有序集合中的所有元素



     */
    public List<ZSkipListNode<T>> rangeByLex(T min, boolean minInclude, T max, boolean maxInclude){

        if(this.length == 0) return null;

        ZSkipListNode start = null;
        if("-".equals(min)) {
            start = header.level[0].forward;
        }else{
            start = findFirstNode(0, min, new WalkerLex(minInclude ? CompareOp.greater_equals : CompareOp.greater), false);

        }
        if("+".equals(max)) {
            max = tail.obj;
            maxInclude = true;
        }

        if(start == null) return null;

        List<ZSkipListNode<T>> list = new ArrayList<>();
        while (start != null) {
            if((minInclude && start.obj.compareTo(min) >= 0)
            || (!minInclude && start.obj.compareTo(min) > 0)){

                if((maxInclude && start.obj.compareTo(max) <= 0)
                        || (!maxInclude && start.obj.compareTo(max) < 0)){
                    list.add(start);
                    start = start.level[0].forward;
                }else{
                    break;
                }
            }else{
                break;
            }
        }

        return list;
    }



    // 如果range给定的数值范围包含在跳跃表的分值范围则返回1，否则返回0
    // int zslIsInRange(zskiplist *zsl, zrangespec *range);
    public int isInRange(double min, double max) {
        double minScore = header.level[0].forward == null ? 0 : header.level[0].forward.score;
        double maxScore = tail == null ? 0 : tail.score;
        if(min >= minScore && max <= maxScore) return 1;
        return 0;
    }

    // 返回跳跃表中第一个分值score在range指定范围的节点
    public ZSkipListNode firstInRange(double min, double max) {
        if(min > max) return null;

        ZSkipListNode node = findFirstNode(min, null, new WalkerScore(CompareOp.greater_equals), false);
        if(node == null) return null;
        if(node.score > max) return null;
        return node;

    }

    // 返回跳跃表中最后一个分值score在range指定范围的节点
    public ZSkipListNode lastInRange(double min, double max) {
//        ZSkipListNode node = firstInRange(min, max);
//        if(node == null) return null;
//        while (true){
//            if(node.score > max) {
//                return node.backward;
//            }else if(node.level[0].forward == null){
//                return node;
//            }else{
//                node = node.level[0].forward;
//            }
//        }
        if(min > max) return null;

        ZSkipListNode node = findFirstNode(max, null, new WalkerScore(CompareOp.greater), false);
        System.out.println("lastInRange: " + node);
        if(node == null) node = tail;

        if(node == null) return null;
        if(node.score < min) return null;
        if(node.score > max) node = node.backward;
        System.out.println("lastInRange-2: " + node);

        return node;
    }

    // 返回指定元素在跳跃表中的排位
    public long getRank(double score, T obj) {
//        ZSkipListNode node = findFirstNode(score, obj, new NodeAccesorScoreAndObjEquals(), false);
//        if(node == null) return -1;

        int rank = 0;

        // 又得执行一遍find操作，应该是没必要了，不过现在凌晨1点了，代码也没精神优化了，先这么地吧
        int workingLevel = this.level - 1;
        ZSkipListNode start = header;
        while (true) {
            if (workingLevel == -1) break; // 0是最底层了，能走到这说明没找到
            ZSkipListNode nextNode = start.level[workingLevel].forward;
            if (nextNode == null) {
                // 当前层到尾了，下移一层
                workingLevel -= 1;
            } else if (nextNode.score > score) {
                // 下一个节点大，说明在中间，下移一层
                workingLevel -= 1;
            } else if (nextNode.score < score) {
                //
                rank += start.level[workingLevel].span;
                start = nextNode;
            } else {
                // score相等
                if (nextNode.obj.compareTo(obj) > 0) {
                    // 下一个节点大，说明在中间，下移一层
                    workingLevel -= 1;
                } else if (nextNode.obj.compareTo(obj) < 0) {
                    //
                    rank += start.level[workingLevel].span;
                    start = nextNode;
                } else {
                    // 相等，就是这个节点了
                    rank += start.level[workingLevel].span;
                    return rank - 1;  // span最小是1，rank是从0开始，所以减一
                }
            }
        }

        return -1;

    }

    // 返回指定排位上的节点
    public ZSkipListNode<T> getElementByRank(long rank) {
        if (rank < 0 || rank >= this.length) return null;
        long remainRank = rank + 1;

        int workingLevel = this.level - 1;
        ZSkipListNode<T> nextNode = header;
        while (true) {
            if (workingLevel == -1) break; // 0是最底层了，能走到这说明没找到
            if (nextNode.level[workingLevel].forward == null) {
                // 当前层到尾了，下移一层[后续节点是null，则当前节点的span就没啥用了]
                workingLevel -= 1;
//                System.out.println("(" + workingLevel + ")" + "下移 -- 本层到头");
            } else if (nextNode.level[workingLevel].span > remainRank) {
                // 下一个节点超了，说明在中间，下移一层
                workingLevel -= 1;
//                System.out.println("(" + workingLevel + ")" + "下移 -- 下一节点超限");
            } else if (nextNode.level[workingLevel].span < remainRank) {
                // 下一个节点还不够，说明在后面，后移一个
                remainRank -= nextNode.level[workingLevel].span;
                nextNode = nextNode.level[workingLevel].forward;
//                System.out.println("(" + workingLevel + ")" + "后移 -- 当前剩余：" + remainRank);
            } else {
                return nextNode.level[workingLevel].forward;
            }


        }

        return null;
    }

    public List<ZSkipListNode<T>> range(int start, int stop){
        int count = stop - start + 1;
        if(count < 0) return null;
        List<ZSkipListNode<T>> list = new ArrayList<>();

        ZSkipListNode<T> nodeStart = getElementByRank(start);
        if(nodeStart == null) return list;
        for (int i = 0; i < count; i++) {
            list.add(nodeStart);
            nodeStart = nodeStart.level[0].forward;
        }

        return list;
    }

    public List<ZSkipListNode<T>> rangeByScore(double min, boolean minInclude, double max, boolean maxInclude){
        List<ZSkipListNode<T>> list = new ArrayList<>();

        ZSkipListNode<T> start = firstInRange(min, max);
        ZSkipListNode<T> end = lastInRange(min, max);
        if(start == null || end == null) return null;

        if(doubleEquals(start.score, min) && !minInclude){
            start = start.level[0].forward;
        }
        if(start == null) return null;

        if(doubleEquals(end.score, max) && !maxInclude){
            end = end.backward;
        }
//        System.out.println(start + " ======》》》》" + end);
        while (start != end){
            list.add(start);
//            System.out.println(start.obj);
            start = start.level[0].forward;
        }
        list.add(end);
        return list;
    }

    public List<ZSkipListNode<T>> revRangeByScore(double min, boolean minInclude, double max, boolean maxInclude){
        List<ZSkipListNode<T>> list = new ArrayList<>();

        ZSkipListNode<T> start = firstInRange(min, max);
        ZSkipListNode<T> end = lastInRange(min, max);
        if(start == null || end == null) return null;

        if(doubleEquals(start.score, min) && !minInclude){
            start = start.level[0].forward;
        }
        if(start == null) return null;

        if(doubleEquals(end.score, max) && !maxInclude){
            end = end.backward;
        }
//        System.out.println(start + " ======》》》》" + end);
        while (end != start){
            list.add(end);
//            System.out.println(start.obj);
            end = end.backward;
        }
        list.add(start);
        return list;
    }

    private static int getRandomLevel() {
        int level = 1;
        while (true) {
            int r = random.nextInt(100); //[0, 99]
            if (r >= 50) {
                // 占用
                level++;
                if (level == ZSKIPLIST_MAXLEVEL - 1) break;
            } else {
                // 不占用
                break;
            }
        }
        return level;
    }

    public void printAllLevels() {
        System.out.println("\n~~ start -----------------------------------");
        for (int i = this.level - 1; i >= 0; i--) {
            printLevel(i);
        }
        System.out.println("~~ end -------------------------------------\n");
    }

    public void printLevel(int level) {
        ZSkipListNode node = header;
        while (true) {
            System.out.print(node.obj + "(" + (node.backward == null ? "/" : (node.backward.obj == null ? "|" : node.backward.obj)) + ")" + " ");
            long span = node.level[level].span;
            if (span > 1) {
                for (int i = 0; i < span - 1; i++) {
                    System.out.print("----" + " ");
                }
            }

            node = node.level[level].forward;
            if (node == null) break;
        }
        System.out.println();
    }

    public static abstract class NodeWalker<T extends Comparable<T>> {

        protected CompareOp op;

        public NodeWalker(CompareOp op) {
            this.op = op;
        }

        /** 找到合适的节点了 */
        public boolean shouldStop(ZSkipListNode<T> node, double score, T obj) {
            if(absoluteAccept(node, score, obj)) return true;
            if(node.score > score || (doubleEquals(node.score, score) && strCompare(node.obj, obj) > 0)) return true;
            return false;
        }


        abstract boolean absoluteAccept(ZSkipListNode<T> node, double score, T obj);

//        public ZSkipListNode firstAcceptedNode(ZSkipListNode prev, double score, String obj) {
//            if(absoluteAccept(prev, score, obj)) return prev;
//            else if(prev.level[0].forward == null) return null;
//            else if(absoluteAccept(prev.level[0].forward, score, obj)) return prev.level[0].forward;
//            else return null;
//        }
    }

    private static enum CompareOp{
        equals, greater, greater_equals
    }

    private static class WalkerScoreAndObj<T extends Comparable<T>> extends NodeWalker<T>{


        public WalkerScoreAndObj(CompareOp op) {
            super(op);
        }

        @Override
        boolean absoluteAccept(ZSkipListNode<T> node, double score, T obj) {
            if(doubleEquals(node.score, score) && strCompare(node.obj, obj) == 0) {
                // ==
                return (op == CompareOp.equals || op == CompareOp.greater_equals);
            }else if(node.score > score || (doubleEquals(node.score, score) && strCompare(node.obj, obj) > 0)){
                // >
                return op == CompareOp.greater_equals || op == CompareOp.greater;
            }else{
                // <
                return false;
            }

        }

    }

    private static class WalkerScore<T extends Comparable<T>> extends NodeWalker<T>{


        public WalkerScore(CompareOp op) {
            super(op);
        }

        @Override
        public boolean absoluteAccept(ZSkipListNode<T> node, double score, T obj) {
            if(doubleEquals(node.score, score)) {
                // ==
                return (op == CompareOp.equals || op == CompareOp.greater_equals);
            }else if(node.score > score){
                // >
                return op == CompareOp.greater_equals || op == CompareOp.greater;
            }else{
                // <
                return false;
            }
        }


    }


    private static class WalkerLex<T extends Comparable<T>> extends NodeWalker<T>{


        public WalkerLex(CompareOp op) {
            super(op);
        }

        @Override
        public boolean absoluteAccept(ZSkipListNode<T> node, double score, T obj) {
            if(strCompare(node.obj, obj) == 0) {
                // ==
                return (op == CompareOp.equals || op == CompareOp.greater_equals);
            }else if(strCompare(node.obj, obj) > 0){
                // >
                return op == CompareOp.greater_equals || op == CompareOp.greater;
            }else{
                // <
                return false;
            }
        }

    }


    public static void main(String[] args) {
        ZSkipList list = new ZSkipList();
        list.insert(11, "a");
        list.insert(13, "c");
        list.insert(14, "d");
        list.insert(12, "b");
        list.insert(16, "f");
        list.insert(15, "e");

//        list.insert(1, "h");
        list.printAllLevels();
//
        list.delete(15, "e");
        list.insert(-15, "e");
        list.printAllLevels();

//        System.out.println(list.firstInRange(-100, 15));
//        System.out.println(list.lastInRange(-100, 15));
        System.out.println(list.rangeByScore(-100, true, 15, true));
    }

}
